package com.zxq.common.middleware;

import com.zxq.common.middleware.gateway.RedisLockGateway;
import com.zxq.common.middleware.lock.*;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class DistributedLock {

    @Resource
    private RedisLockGateway redisLockGateway;

    public Lock getLock(String lockKey) {
        RedisLock redisLock = new RedisLock(
                lockKey,
                redisProcessor,
                lockOwnershipWatchDag,
                DistributeLockConstants.RedisLockConstants.EXPIRE_TIME,
                DistributeLockConstants.RedisLockConstants.RETRY);
        return redisLock;
    }

    public Lock getLock(List<String> lockKeys) {
        RedisMultiLock redisMultiLock = new RedisMultiLock(
                lockKeys,
                redisProcessor,
                lockOwnershipWatchDag,
                DistributeLockConstants.RedisLockConstants.EXPIRE_TIME,
                DistributeLockConstants.RedisLockConstants.RETRY);

        return redisMultiLock;
    }


    //////////////////////////////////////////////////////////////////////////////////

    /**
     * watchdog续租间隔nanosecond
     */
    private static final long WATCH_DOG_INTERVAL_NANO = TimeUnit.MILLISECONDS.toNanos(500);

    /**
     * 每次续租时长nanosecond
     */
    private static final long WATCH_DOG_STEP_NANO = TimeUnit.MILLISECONDS.toNanos(2000);

    /**
     * watchdog持有lock的map的初始大小
     */
    private static final int WATCH_DOG_INIT_SIZE = 100;

    private RedisProcessor redisProcessor;

    private static final RenewalWatchdog lockOwnershipWatchDag = new RedisLockWatchdog(WATCH_DOG_INTERVAL_NANO, WATCH_DOG_STEP_NANO, WATCH_DOG_INIT_SIZE);


    @PostConstruct
    public void init() throws Exception {
        redisProcessor = new RedisProcessor(redisLockGateway);
    }

}
